// FindFeatureCode.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include<Windows.h>
#include<iostream>
#include<vector>
#include<time.h>
#include<string>
#include<string.h>
#include<iomanip>

using namespace std;

#define PAGE_SIZE 0x1024


#define DAZUO "0123456789ABCDEF"  // 打坐特征码
#define OPEN_PNC_DIALOG "8B542410C7000000000052"  // 打坐特征码
#define XUN_LU "D94044D94040D9403C83C00C83C604"  // 寻路特征码

void BytesToHexStr(BYTE* ndData, DWORD ndDataSize, char* szpHexBuf) {
	// 确保缓冲区足够大
	if (szpHexBuf == nullptr || ndData == nullptr || ndDataSize == 0) {
		return; // 或者你可以抛出一个异常
	}

	char hexMap[] = "0123456789ABCDEF";
	for (DWORD i = 0; i < ndDataSize; ++i) {
		BYTE byte = ndData[i];
		// 将高4位转换成16进制字符
		szpHexBuf[i * 2] = hexMap[(byte >> 4) & 0xF];
		// 将低4位转换成16进制字符
		szpHexBuf[i * 2 + 1] = hexMap[byte & 0xF];
	}
	// 添加字符串终止符
	szpHexBuf[ndDataSize * 2] = '\0';
}

DWORD HexStrCmp(const char *a, char*b, DWORD ndLenHexCode) {
	for (int i = 0;i < ndLenHexCode;i++) {
		if (a[i] != b[i]) {
			return FALSE;
		}
	}
	return TRUE;
}


DWORD scanFeatureCode(HANDLE hProess, IN OUT  const char* szpnFeatureCode, DWORD ndStartAdress = 0x40000000, DWORD ndEndAdress =0x7FFFFFFF) 
{
	DWORD ndLenHexCode = strlen(szpnFeatureCode);
	int arraryLen = PAGE_SIZE + ndLenHexCode / 2 + 2;
	BYTE* ndDateBuffer = new BYTE[arraryLen];
	DWORD ndByReadSize = 0; // 实际读取大小
	for (DWORD ndCurAddr = ndStartAdress;ndCurAddr < ndEndAdress- ndLenHexCode/2;ndCurAddr++) {
		ReadProcessMemory(hProess, (LPVOID)ndCurAddr, (LPVOID)ndDateBuffer, arraryLen, &ndByReadSize);
		// 开始比较
		for (DWORD i = 0;i < PAGE_SIZE;i++) {
			char szpTempHex[256] = "";
			BytesToHexStr(&ndDateBuffer[i], ndLenHexCode / 2, szpTempHex);

			if (HexStrCmp(szpnFeatureCode, szpTempHex, ndLenHexCode)== TRUE) {
				return ndCurAddr + i;
			}
		}
	}

	//HexStrToBigCase(szpnFeatureCode);
	return NULL;
}

int main()
{
	//初始化MemoryData大小

	HWND gameHwnd = FindWindowA("QElementClient Window", "天军2_已停止");
	if (gameHwnd == NULL) {
		cout << "gameHwnd == NULL" << endl;
		return 0;
	}
	DWORD pid;
	GetWindowThreadProcessId(gameHwnd, &pid);
	if (pid == 0) {
		cout << "游戏进程ID：获取失败" << pid << endl;
		return 0;
	}
	printf("游戏进程ID：%x(%d)", pid, pid);
	//通过进程ID获取进程句柄
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
	if (hProcess == NULL) {
		cout << "游戏hProcess 获取失败" << pid << endl;
		return 0;
	}
	char szpnFeatureCode[] = "C1E805F6D0240150";
	int start = clock();
	DWORD result = scanFeatureCode(hProcess, szpnFeatureCode, 0x004FB800);
	int end = clock();
	cout << "用时：" << end - start << "毫秒" << endl;
	cout << "长度为：" << sizeof(szpnFeatureCode)/2 << endl;
	printf("打坐Call 		 \r地址为：%x \n", result + sizeof(szpnFeatureCode)/ 2);
	printf("打开PNC对话Call  \r地址为：%x \n", scanFeatureCode(hProcess, OPEN_PNC_DIALOG, 0x007B7000) + sizeof(OPEN_PNC_DIALOG)/ 2);
	printf("打开PNC对话Call  \r地址为：%x \n", scanFeatureCode(hProcess, OPEN_PNC_DIALOG, 0x007B75ff) + sizeof(OPEN_PNC_DIALOG)/ 2);
	printf("寻路Call  \r地址为：%x \n", scanFeatureCode(hProcess, XUN_LU, 0x00520000) + sizeof(XUN_LU)/ 2);
	//printf("打开PNC对话Call  \r地址为：%x \n", scanFeatureCode(hProcess, OPEN_PNC_DIALOG, 0x007B7691, 0x007EFFFF) + sizeof(OPEN_PNC_DIALOG)/ 2);

	system("pause");
	cin >> pid;
	return 0;
}